package com.yxsk.relay.job.endpoint.combine.loader;

import com.alibaba.fastjson.JSONObject;
import com.yxsk.relay.job.component.common.utils.CollectionUtils;
import com.yxsk.relay.job.endpoint.combine.config.ConfigPropertiesPrefix;
import com.yxsk.relay.job.endpoint.combine.exception.config.ConfigLoadException;
import com.yxsk.relay.job.endpoint.combine.exception.resource.ResourceLoadException;
import org.apache.commons.lang3.StringUtils;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description
 * @Author 11376
 * @CreateTime 2019/9/10 21:01
 */
public class ApplicationConfigLoader {

    public <T> T load(String path, Class<T> configType) {
        // 变量
        Map<String, Object> variableMap = new HashMap<>();

        // 加载配置文件
        if (StringUtils.isNotEmpty(path)) {
            ResourceLoader loader;
            if (path.startsWith("classpath:")) {
                loader = new ClassPathResourceLoader();
            } else {
                throw new ResourceLoadException("Unsupported profile load type.(" + path + ")");
            }
            Map map = loader.load(path, Map.class);
            if (CollectionUtils.isNotEmpty(map)) {
                variableMap.putAll(map);
            }
        }

        // 加载环境变量
        /*SystemEnvironmentVariableLoader environmentVariableLoader = new SystemEnvironmentVariableLoader();
        Map<String, String> environmentVariables = environmentVariableLoader.getAllProperties();
        if (CollectionUtils.isNotEmpty(environmentVariables)) {
            // 转为Map节点类型变量
            Map<String, Object> map = convertVariables(environmentVariables);

            // 同步 key 值替换
            Map<String, Object> finalVariableMap = variableMap;
            map.entrySet().stream().forEach(entry -> {
                Object value = entry.getValue();
                Object originalVar = finalVariableMap.get(entry.getKey());
                if (value instanceof Map) {
                    if (originalVar == null) {
                        finalVariableMap.put(entry.getKey(), value);
                    } else {
                        // 继续下一层

                    }
                } else {
                    finalVariableMap.put(entry.getKey(), value);
                }
            });
        }*/

        // 注入变量
        ConfigPropertiesPrefix propertiesPrefix = configType.getAnnotation(ConfigPropertiesPrefix.class);
        if (propertiesPrefix != null) {
            String prefix = propertiesPrefix.value();
            if (StringUtils.isNotEmpty(prefix)) {
                String[] nodes = prefix.split("\\.");
                for (String node : nodes) {
                    Object o = variableMap.get(node);
                    if (o == null) {
                        variableMap = Collections.EMPTY_MAP;
                        break;
                    }
                    if (o instanceof Map) {
                        variableMap = (Map<String, Object>) o;
                    } else {
                        // 实体
                        if (configType.isInstance(o)) {
                            return (T) o;
                        } else {
                            throw new ConfigLoadException("Variable type transfer error, config type: " + configType.getName() + ", search variable: " + o);
                        }
                    }
                }
            }
        }

        // 实例化对象
        String json = JSONObject.toJSONString(variableMap);
        if (StringUtils.isNotEmpty(json)) {
            return JSONObject.parseObject(json, configType);
        }
        try {
            return configType.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new ConfigLoadException(e);
        }
    }

    private Map<String, Object> convertVariables(Map<String, String> environmentVariables) {
        Map<String, Object> map = new HashMap<>();
        environmentVariables.entrySet().stream().forEach(entry -> {
            String key = entry.getKey();
            String[] path = key.split("\\.");

            if (path.length == 1) {
                map.put(path[0], entry.getValue());
                return;
            }
            Map<String, Object> temp = map;
            for (int i = 0; i < path.length - 1; i++) {
                Object o = temp.get(path[i]);
                if (o == null) {
                    Map<String, Object> child = new HashMap<>();
                    temp.put(path[i], child);
                    temp = child;
                } else if (o instanceof Map) {
                    temp = (Map<String, Object>) o;
                }
            }
            temp.put(path[path.length - 1], entry.getValue());
        });
        return map;
    }

}
